#include "EZ_Thread.h"


ez_thread_t*	get_thread_self(void)
{
	return cur_task;
}

void stack_init(ez_thread_t 	*task, 
								void 					(*entry)(void *), 
								void 					*param, 
								uint32_t 			*stack)
{
		struct stack_frame *stack_frame;
		stack -= sizeof(struct stack_frame);
		stack_frame = (struct stack_frame *)(stack);
		stack_frame->exception_stack_frame.r0 = (uint32_t)param;
		stack_frame->exception_stack_frame.r1 = 0;
		stack_frame->exception_stack_frame.r2 = 0;
		stack_frame->exception_stack_frame.r3 = 0;
		stack_frame->exception_stack_frame.r12 = 0;
		stack_frame->exception_stack_frame.lr = (uint32_t)task_exit;
		stack_frame->exception_stack_frame.pc = (uint32_t)entry;
		stack_frame->exception_stack_frame.psr = 0x01000000L;

    task->sp = stack;    
}

void task_init(ez_thread_t 	*task, 
							void 					(*entry)(void *), 
							void 					*param, 
							uint32_t 			*stack,
              uint8_t        priority,
              uint32_t       tick)
{
		stack_init(task,entry,param,stack);
	
		list_init(&(task->tlist));
		timer_init(&task->timer,0,thread_timeout,(void *)task,EZ_TIMER_ONCE);
	
		task->entry = entry;
		task->parameter = param;
		task->init_priority = task->current_priority = priority;
		task->init_tick = task->remaining_tick = tick;
		task->stat = EZ_THREAD_INIT;
		task->cleanup = 0;
	
		
		
}

void task_startup(ez_thread_t *task)
{
	
	ez_enter_critical();
	
	task->stat = EZ_THREAD_READY;
	
	task->remaining_tick = task->init_tick;
	task->current_priority = task->init_priority;

	scheduler_insert_thread(task);
	
	ez_exit_critical();

}

void task_exit(void)
{
	uint32_t state;
	ez_thread_t* thread;

	state = ez_hw_interrupt_disable();

	thread = get_thread_self();

	scheduler_remove_thread(thread);
	
	if(thread->cleanup != EZ_NULL)
	{
		thread->cleanup(0);
	}
	
	thread->stat = EZ_THREAD_CLOSE;
	
	ez_hw_interrupt_enable(state);
	
	task_scheduler();
	
}

void task_yield(void)
{
	ez_thread_t *thread;
	thread = cur_task;
		
	list_remove(&thread->tlist);
	
	scheduler_insert_thread(thread);
	
	thread->stat = EZ_THREAD_READY;
	task_scheduler();
}

void task_suspend(ez_thread_t *thread)
{
	uint32_t state;
	state = ez_hw_interrupt_disable();

	scheduler_remove_thread(thread);
	thread->stat = EZ_THREAD_SUSPEND;
	timer_stop(&thread->timer);
	
	ez_hw_interrupt_enable(state);
}	

void task_resume(ez_thread_t *thread)
{
	uint32_t state;
	state = ez_hw_interrupt_disable();

	list_remove(&thread->tlist);
	timer_stop(&thread->timer);
	scheduler_insert_thread(thread);
	
	ez_hw_interrupt_enable(state);
}

void task_sleep(uint32_t tick)
{

	ez_enter_critical();
	
	scheduler_remove_thread(cur_task);
	
	timer_contorl(&cur_task->timer,EZ_TIME_CTRL_SET_TIME,(void *)tick);
	timer_start(&cur_task->timer);
	
	ez_exit_critical();

	task_scheduler();

}

void thread_timeout(void *param)
{
	ez_thread_t *thread;
	thread = (ez_thread_t *)param;
	
	list_remove(&thread->tlist);
	
	scheduler_insert_thread(thread);
	
	task_scheduler();
	
}

